const Redis = require('ioredis');
const net = require('net');

console.log('🔍 Redis连接问题诊断脚本');
console.log('==============================');
console.log('');

// 目标服务器信息
const TARGET_HOST = '43.143.253.188';
const TARGET_PORT = 6379;
const TARGET_PASSWORD = 'jack666';

console.log(`📍 目标服务器: ${TARGET_HOST}:${TARGET_PORT}`);
console.log(`🔑 密码: ${TARGET_PASSWORD}`);
console.log('');

// 1. 网络连通性测试
async function testNetworkConnectivity() {
  console.log('🌐 测试1: 网络连通性检查');
  console.log('------------------------');
  
  try {
    // 使用net模块测试TCP连接
    const socket = new net.Socket();
    
    const connectPromise = new Promise((resolve, reject) => {
      const timeout = setTimeout(() => {
        socket.destroy();
        reject(new Error('连接超时'));
      }, 10000);
      
      socket.connect(TARGET_PORT, TARGET_HOST, () => {
        clearTimeout(timeout);
        console.log('✅ TCP连接成功建立');
        socket.destroy();
        resolve();
      });
      
      socket.on('error', (error) => {
        clearTimeout(timeout);
        console.log(`❌ TCP连接失败: ${error.code} - ${error.message}`);
        reject(error);
      });
    });
    
    await connectPromise;
    return true;
  } catch (error) {
    console.log(`❌ 网络连通性测试失败: ${error.message}`);
    
    // 根据错误代码提供建议
    switch (error.code) {
      case 'ECONNREFUSED':
        console.log('');
        console.log('💡 ECONNREFUSED 错误分析:');
        console.log('   1. Redis服务器未运行');
        console.log('   2. Redis配置不允许远程连接');
        console.log('   3. 防火墙阻止连接');
        console.log('   4. 端口被其他服务占用');
        break;
      case 'ETIMEDOUT':
        console.log('');
        console.log('💡 ETIMEDOUT 错误分析:');
        console.log('   1. 网络延迟过高');
        console.log('   2. 防火墙规则问题');
        console.log('   3. 网络路由问题');
        break;
      case 'ENOTFOUND':
        console.log('');
        console.log('💡 ENOTFOUND 错误分析:');
        console.log('   1. IP地址错误');
        console.log('   2. DNS解析问题');
        break;
      default:
        console.log('');
        console.log('💡 其他网络问题，建议检查:');
        console.log('   1. 网络配置');
        console.log('   2. 防火墙设置');
        console.log('   3. 服务器状态');
    }
    
    return false;
  }
}

// 2. Redis协议测试
async function testRedisProtocol() {
  console.log('');
  console.log('🔌 测试2: Redis协议测试');
  console.log('------------------------');
  
  try {
    const socket = new net.Socket();
    
    const protocolTest = new Promise((resolve, reject) => {
      const timeout = setTimeout(() => {
        socket.destroy();
        reject(new Error('协议测试超时'));
      }, 15000);
      
      let responseData = '';
      
      socket.connect(TARGET_PORT, TARGET_HOST, () => {
        console.log('✅ 建立TCP连接，开始Redis协议测试...');
        
        // 发送Redis PING命令
        const pingCommand = '*1\r\n$4\r\nPING\r\n';
        socket.write(pingCommand);
        console.log('📤 发送: PING命令');
      });
      
      socket.on('data', (data) => {
        responseData += data.toString();
        console.log(`📥 收到响应: ${data.toString().trim()}`);
        
        if (responseData.includes('+PONG') || responseData.includes('PONG')) {
          clearTimeout(timeout);
          console.log('✅ Redis协议测试成功 - 服务器响应PONG');
          socket.destroy();
          resolve();
        }
      });
      
      socket.on('error', (error) => {
        clearTimeout(timeout);
        console.log(`❌ Redis协议测试失败: ${error.message}`);
        reject(error);
      });
      
      socket.on('close', () => {
        clearTimeout(timeout);
        if (!responseData.includes('+PONG') && !responseData.includes('PONG')) {
          reject(new Error('连接关闭，未收到有效响应'));
        }
      });
    });
    
    await protocolTest;
    return true;
  } catch (error) {
    console.log(`❌ Redis协议测试失败: ${error.message}`);
    return false;
  }
}

// 3. 认证测试
async function testRedisAuth() {
  console.log('');
  console.log('🔐 测试3: Redis认证测试');
  console.log('------------------------');
  
  try {
    const redis = new Redis({
      host: TARGET_HOST,
      port: TARGET_PORT,
      password: TARGET_PASSWORD,
      db: 0,
      connectTimeout: 10000,
      commandTimeout: 5000,
      retryDelayOnFailover: 100,
      maxRetriesPerRequest: 1,
      lazyConnect: true,
    });
    
    // 监听连接事件
    redis.on('connect', () => {
      console.log('✅ Redis连接建立');
    });
    
    redis.on('ready', () => {
      console.log('✅ Redis服务器就绪');
    });
    
    redis.on('error', (error) => {
      console.log(`❌ Redis错误: ${error.message}`);
    });
    
    redis.on('close', () => {
      console.log('🔌 Redis连接关闭');
    });
    
    // 尝试连接
    console.log('🔄 尝试Redis连接...');
    await redis.connect();
    
    // 测试PING
    const pingResult = await redis.ping();
    console.log(`✅ PING测试成功: ${pingResult}`);
    
    // 测试基本操作
    await redis.set('test:auth', 'Hello Redis Auth!', 'EX', 60);
    const value = await redis.get('test:auth');
    console.log(`✅ 认证后操作测试成功: ${value}`);
    
    // 清理测试数据
    await redis.del('test:auth');
    
    await redis.quit();
    return true;
  } catch (error) {
    console.log(`❌ Redis认证测试失败: ${error.message}`);
    
    if (error.message.includes('NOAUTH')) {
      console.log('');
      console.log('💡 NOAUTH 错误分析:');
      console.log('   1. 密码错误');
      console.log('   2. Redis未设置密码');
      console.log('   3. 认证配置问题');
    } else if (error.message.includes('ECONNREFUSED')) {
      console.log('');
      console.log('💡 连接被拒绝，可能的原因:');
      console.log('   1. Redis服务器未运行');
      console.log('   2. 配置不允许远程连接');
      console.log('   3. 防火墙阻止');
    }
    
    return false;
  }
}

// 4. 配置建议
function provideConfigurationSuggestions() {
  console.log('');
  console.log('🔧 配置建议');
  console.log('-------------');
  console.log('');
  
  console.log('📋 Redis服务器端配置检查:');
  console.log('   1. 检查Redis是否运行: systemctl status redis');
  console.log('   2. 检查端口监听: netstat -tlnp | grep 6379');
  console.log('   3. 检查配置文件: /etc/redis/redis.conf');
  console.log('   4. 检查bind设置: bind 0.0.0.0 或 bind 43.143.253.188');
  console.log('   5. 检查protected-mode: protected-mode no');
  console.log('   6. 检查防火墙: ufw status 或 iptables -L');
  console.log('');
  
  console.log('📋 客户端配置建议:');
  console.log('   1. 确认IP地址正确');
  console.log('   2. 确认端口号正确');
  console.log('   3. 确认密码正确');
  console.log('   4. 调整连接超时时间');
  console.log('   5. 启用重试机制');
  console.log('');
  
  console.log('📋 网络配置检查:');
  console.log('   1. 检查服务器网络配置');
  console.log('   2. 检查路由器/防火墙规则');
  console.log('   3. 检查云服务商安全组设置');
  console.log('   4. 检查VPC网络配置');
}

// 5. 替代方案
function provideAlternatives() {
  console.log('');
  console.log('🔄 替代方案');
  console.log('-------------');
  console.log('');
  
  console.log('💡 如果远程Redis无法连接，可以考虑:');
  console.log('   1. 使用本地Redis进行开发测试');
  console.log('   2. 使用Docker运行Redis容器');
  console.log('   3. 使用云Redis服务');
  console.log('   4. 检查服务器网络配置');
  console.log('   5. 联系服务器管理员');
}

// 主诊断函数
async function runDiagnosis() {
  try {
    console.log('🚀 开始Redis连接诊断...');
    console.log('');
    
    // 运行各项测试
    const networkOk = await testNetworkConnectivity();
    const protocolOk = await testRedisProtocol();
    const authOk = await testRedisAuth();
    
    console.log('');
    console.log('📊 诊断结果汇总');
    console.log('==================');
    console.log(`🌐 网络连通性: ${networkOk ? '✅ 正常' : '❌ 异常'}`);
    console.log(`🔌 Redis协议: ${protocolOk ? '✅ 正常' : '❌ 异常'}`);
    console.log(`🔐 认证测试: ${authOk ? '✅ 正常' : '❌ 异常'}`);
    
    if (networkOk && protocolOk && authOk) {
      console.log('');
      console.log('🎉 所有测试通过！Redis连接正常');
    } else {
      console.log('');
      console.log('⚠️ 发现问题，请查看上述详细错误信息');
      
      // 提供配置建议
      provideConfigurationSuggestions();
      
      // 提供替代方案
      provideAlternatives();
    }
    
  } catch (error) {
    console.error('❌ 诊断过程出错:', error.message);
  }
  
  console.log('');
  console.log('🔍 诊断完成');
}

// 运行诊断
runDiagnosis(); 